블로그 릴레이 - CDK 로 Amazon Cognito 리소스를 이용해서 Amazon API Gateway에 Authorizer 설정 해보기

블로그 릴레이 - CDK 로 Amazon Cognito 리소스를 이용해서 Amazon API Gateway에 Authorizer 설정 해보기

안녕하세요 생산지원 그룹 리테일 어플리케이션부의 김승연입니다. 본 블로그는 당사의 한국어 블로그 릴레이의 24번째 블로그입니다. 이번 블로그 주제는 「CDK 로 Amazon Cognito 리소스를 이용해서 Amazon API Gateway에 Authorizer 설정 해보기」 입니다.
Clock Icon2024.12.07

안녕하세요 생산지원 그룹 리테일 어플리케이션부의 김승연입니다.

본 블로그는 당사의 한국어 블로그 릴레이의 24번째 블로그입니다.
이번 블로그 주제는 「CDK 로 Amazon Cognito 리소스를 이용해서 Amazon API Gateway에 Authorizer 설정 해보기」 입니다.

개요

이번에는 이전에 작성한 블로그에서 작성한 API에 인증된 사용자만 접속할 수 있도록 Amazon Cognito 리소스를 생성 후 Amazon API Gateway에 Authorizer 설정을 추가해 보았습니다.

코드 작성

이전에 작성한 블로그 릴레이 - CDK 와 Serverless express 사용해 보기의 리소스를 이용해 준비 과정은 빠르게 스킵하고 바로 코드를 작성해 보도록 하겠습니다.

...
    // Cognito user pool
    const cognitoUserPool = new cdk.aws_cognito.UserPool(this, 'userPool', {
      userPoolName: 'userPool',
      standardAttributes: { email: { required: true, mutable: false } }, // 이메일 필수・수정 불가
      autoVerify: { email: true }, // 이메일 자동 인증
    });

    cognitoUserPool.addClient('clientCognitoUserPool', {
      userPoolClientName: 'clientCognitoUserPool',
      authFlows: { adminUserPassword: true, userPassword: true },
    });

    // Cognito Authorizer
    const cognitoUserPoolsAuthorizer =
      new aws_apigateway.CognitoUserPoolsAuthorizer(
        this,
        'CognitoUserPoolsAuthorizer',
        {
          cognitoUserPools: [cognitoUserPool],
        },
      );

    // Lambda
    const restApiFunc = new cdk.aws_lambda_nodejs.NodejsFunction(
      this,
      'RestApiFunc',
      {
        architecture: cdk.aws_lambda.Architecture.ARM_64,
        runtime: cdk.aws_lambda.Runtime.NODEJS_20_X,
        entry: "../server/src/index.ts",
      }
    );

    // APIGateway REST API
    const restApi = new cdk.aws_apigateway.LambdaRestApi(this, 'RestApi', {
      handler: restApiFunc,
      defaultCorsPreflightOptions: {
        allowOrigins: cdk.aws_apigateway.Cors.ALL_ORIGINS,
        allowMethods: cdk.aws_apigateway.Cors.ALL_METHODS,
        allowHeaders: cdk.aws_apigateway.Cors.DEFAULT_HEADERS,
        maxAge: cdk.Duration.minutes(5),
      }, 
      deployOptions: {
        stageName: 'v1', 
        tracingEnabled: false, 
      },
      defaultMethodOptions: {
        authorizer: cognitoUserPoolsAuthorizer, // API Gateway 에 Authorizer 설정 
      },
    });

    // API Gateway EndPoint
    new cdk.CfnOutput(this, 'RestApiEndpoint', {
      value: restApi.deploymentStage.urlForPath(),
    });
...

아래의 코드 작성이 완료되었다면 다음으로는 배포 후 실제로 동작 하는지 확인해 보겠습니다.

확인

1.CDK를 Deploy를 해줍니다.

npm run cdk bootstrap ← 최초만 실행 
npm run cdk deploy

2.다음으로 실제 리소스 가 생성되어 있는지 확인 후 "사용자 관리"→"사용자" 탭으로 이동 후 사용자를 만듭니다.

create_cognito_user_kr

3.다음으로 사용자를 생성하였다면 아래를 실행해 Token을 습득합니다.

조금 번거롭지만, Amazon Cognito 에서는 초기 패스워드 변경이 필수 옵션으로 되어 있어, Token 습득을 위해서는 패스워드 변경 과정이 필요합니다.

1.
curl -X POST \
 -H "Content-Type: application/x-amz-json-1.1" \
 -H "X-Amz-Target: AWSCognitoIdentityProviderService.InitiateAuth" \
 -d $'{
"AuthParameters": {
  "USERNAME": "유저명",
  "PASSWORD": "이메일을 통해 받은 임시 패스워드"
},
"AuthFlow": "USER_PASSWORD_AUTH",
"ClientId": "Amazon cognito clientId"
}' \
https://cognito-idp.[region].amazonaws.com/

2.
curl -X POST \
 -H "Content-Type: application/x-amz-json-1.1" \
 -H "X-Amz-Target: AWSCognitoIdentityProviderService.RespondToAuthChallenge" \
 -d $'{
"ChallengeName": "NEW_PASSWORD_REQUIRED",
"ChallengeResponses": {
  "USERNAME": "유저명",
  "PASSWORD": "기존의 임시 패스워드",
  "NEW_PASSWORD": "새로 설정할 패스워드"
},
"ClientId": "Amazon cognito clientId",
"Session": "위에서 Response 된 Session"
}' \
https://cognito-idp.[region].amazonaws.com/

4.마지막으로 습득한 토큰을 Header에 설정해 확인합니다.

curl -X GET -H "Content-Type: application/json" -H "Authorization: IdToken" https://xxxxxxxx.execute-api.[region].amazonaws.com/v1/...

보충

만약 기존에 작성된 Amazon Cognito 리소스가 있다면 Cognito UserPoolId를 참조 후 설정하셔도 됩니다.

...
    // Cognito user pool 참조
    const cognitoUserPool = aws_cognito.UserPool.fromUserPoolId(
      this,
      'UserPool',
      'Cognito UserPoolId 지정',
    );

    // Cognito Authorizer
    const cognitoUserPoolsAuthorizer =
      new aws_apigateway.CognitoUserPoolsAuthorizer(
        this,
        'CognitoUserPoolsAuthorizer',
        {
          cognitoUserPools: [cognitoUserPool],
        },
      );

    // Lambda
    const restApiFunc = new cdk.aws_lambda_nodejs.NodejsFunction(
      this,
      'RestApiFunc',
      {
        architecture: cdk.aws_lambda.Architecture.ARM_64,
        runtime: cdk.aws_lambda.Runtime.NODEJS_20_X,
        entry: "../server/src/index.ts",
      }
    );

    // APIGateway REST API
    const restApi = new cdk.aws_apigateway.LambdaRestApi(this, 'RestApi', {
      handler: restApiFunc,
      defaultCorsPreflightOptions: {
        allowOrigins: cdk.aws_apigateway.Cors.ALL_ORIGINS,
        allowMethods: cdk.aws_apigateway.Cors.ALL_METHODS,
        allowHeaders: cdk.aws_apigateway.Cors.DEFAULT_HEADERS,
        maxAge: cdk.Duration.minutes(5),
      }, 
      deployOptions: {
        stageName: 'v1', 
        tracingEnabled: false, 
      },
      defaultMethodOptions: {
        authorizer: cognitoUserPoolsAuthorizer, // API Gateway 에 Authorizer 설정 
      },
    });

    // API Gateway EndPoint
    new cdk.CfnOutput(this, 'RestApiEndpoint', {
      value: restApi.deploymentStage.urlForPath(),
    });
...

참고자료

Amazon Cognito 사용자 풀을 권한 부여자로 사용하여 REST API에 대한 액세스 제어
블로그 릴레이 - CDK 와 Serverless express 사용해 보기

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.